﻿
using System;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;

namespace CollectionUpdateWatcher
{
    /// <summary>
    /// Watch a collection for updates, run, automatically, the DZ guy each time such a thing shows up.
    /// </summary>
    class Program
    {
        /// <summary>
        /// Arguments:
        /// The base directory where we can find the colleciton info.
        /// The output directory where we should write all the various DZ's.
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            if (args.Length != 2)
                throw new ArgumentException("Usage: CollectionUpdateWatcher <dir-of-collection-db> <root-dz-output-dir>");

            var rootDBLoc = args[0];
            var dzLoc = args[1];

            //
            // We want to use utilities, etc., so setup the configuration parameters so we can
            // run by cmd line rather than config file
            //

            ConfigurationManager.AppSettings["ROOTXMLDirectory"] = rootDBLoc;

            //
            // Pretty simple. Watch for file changes in the render directory.
            //

            bool exitNow = false;

            var fsw = new FileSystemWatcher(PivotIO.XML.Utils.GetRenderWatchDirectory().FullName);
            fsw.Error += (s, e) => { Console.WriteLine("File watcher error {0}.", e.GetException().Message); exitNow = true; };
            fsw.Created += (s, e) => { ScanForJobs(dzLoc); };
            fsw.IncludeSubdirectories = false;
            fsw.EnableRaisingEvents = true;

            // Mess from last time?
            ScanForJobs(dzLoc);

            // Wait until somethign unfortunate (??) happens.

            while (!exitNow)
                Thread.Sleep(1000);
        }

        static Mutex _scanLock = new Mutex();

        /// <summary>
        /// Check the directory for a job or 3.
        /// </summary>
        private static void ScanForJobs(string dzRootDir)
        {
            // Carefully control the number of jobs we run in here!
            lock (_scanLock)
            {
                while (true)
                {
                    // If no more files, then exit. Otherwise get the oldest one.

                    var fi = PivotIO.XML.Utils.GetRenderWatchDirectory().EnumerateFiles().OrderBy(f => f.LastWriteTime).FirstOrDefault();
                    if (fi == null)
                        return;

                    // Delete the token file.

                    bool deleted = false;
                    while (!deleted)
                    {
                        try
                        {
                            fi.Delete();
                            deleted = true;
                        }
                        catch
                        {
                            Thread.Sleep(250);
                        }
                    }

                    // And run the sub process to do the rendering.
                    Console.WriteLine("** Trying to render collection {0}", fi.Name);
                    var dzOutput = new DirectoryInfo(Path.Combine(dzRootDir, fi.Name));
                    var psi = new ProcessStartInfo("BuildPivotCollection.exe", string.Format("{0} {1} {2}", PivotIO.XML.Utils.GetROOTDataDirectory(), fi.Name, dzOutput.FullName));

                    psi.UseShellExecute = false;

                    var p = Process.Start(psi);
                    p.WaitForExit();
                    Console.WriteLine("** Exit code from running render for {0} was {1}.", fi.Name, p.ExitCode);
                }
            }
        }
    }
}
